home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
math
/
differ.zip
/
SIMPLIFY.C
< prev
Wrap
C/C++ Source or Header
|
1996-02-11
|
17KB
|
582 lines
#include "differ.h"
/*
This is a recursive routine to check two expressions for equality.
Its useful in simplifying.
*/
logical equaltrees(struct expression *tree1,struct expression *tree2)
{ if((tree1==NULL)&&(tree2==NULL)) return TRUE;
if(tree1==NULL) return FALSE;
if(tree2==NULL) return FALSE;
if(tree1->exptype==tree2->exptype)
{ switch(tree1->exptype)
{ case OPERATOR:if(tree1->expval.op==tree2->expval.op)
return ((equaltrees(tree1->lval,tree2->lval))&(equaltrees(tree1->rval,tree2->rval)));
else return FALSE;
case FUNCTION:if(tree1->expval.fn==tree2->expval.fn)
return (equaltrees(tree1->rval,tree2->rval));
else return FALSE;
case X: return TRUE;
case VALUE: if(tree1->cval==tree2->cval) return TRUE;
else return FALSE;
case CONSTANT:if(tree1->expval.co==tree2->expval.co)
return TRUE;
else return FALSE;
default: return FALSE;
}
}
return FALSE;
}
/*
Heres the simplify routine.
Some simplifications are quite easy like
u * 1 = u
u * 0 = 0
Others are more complicated like moving unitary minuses up the tree.
If you alter this then be careful. The routine is highly recursive
and its easy to create recursive loops where simplifications are
working against each other.
Its also questionable in some circumstances whether you want to make
a change. For example consider
3*(x+1)
Do you want to change this to
3*x+3
because if you do then you might find cases where the output is
(3*x+3)/(x+1) say
whereas before it was
3
because the x+1's cancelled.
On the other hand if you look at the examples carefully, one gives an
output which contains
7*(7*x+1)+7*(7*x-1)
Here this should more easily be
98*x
but how do you get to this and still provide for all the other cases ?
I leave it to you to decide.
One other thing, I've done some manipulations with the pointers in
manipulating expressions, so change things carefully.
*/
struct expression *simplify(struct expression *expr)
{ struct expression *lv,
*rv;
if(expr==NULL) return NULL;
expr->lval=simplify(expr->lval);
expr->rval=simplify(expr->rval);
if (expr->exptype==VALUE)
{ if (expr->cval<0)
{ expr->cval=-expr->cval;
lv=newtree();
lv->exptype=OPERATOR;
lv->expval.op=UMINUS;
lv->rval=expr;
return lv;
}
}
if (expr->exptype==OPERATOR)
{ lv=expr->lval;
rv=expr->rval;
switch(expr->expval.op)
{ case TIMES: if((rv->exptype==OPERATOR)&&((rv->expval.op==TIMES)||(rv->expval.op==DIVIDE)))
{ while((rv->exptype==OPERATOR)&&(rv->expval.op==TIMES))
rv=rv->rval;
if((rv->exptype==OPERATOR)&&(rv->expval.op==DIVIDE))
{ if(equaltrees(rv->rval,lv))
{ lv=expr->rval;
expr->rval=NULL;
freetree(expr);
freetree(rv->rval);
expr=lv;
lv=newtree();
lv->exptype=VALUE;
lv->cval=1;
rv->rval=lv;
return simplify(expr);
}
}
rv=expr->rval;
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==TIMES))
{ expr->lval=lv->rval;
lv->rval=expr;
return simplify(lv);
}
else if(((rv->exptype)<(lv->exptype))&&(((lv->exptype)<OPERATOR)
||((lv->exptype==OPERATOR)&&(rv->exptype==VALUE))))
{ expr->lval=rv;
expr->rval=lv;
lv=expr->lval;
rv=expr->rval;
return simplify(expr);
}
if((rv->exptype==OPERATOR)&&((rv->expval.op==TIMES)||(rv->expval.op==DIVIDE)))
{ if((lv->exptype)>(rv->lval->exptype))
{ expr->lval=rv->lval;
rv->lval=lv;
lv=expr->lval;
return simplify(expr);
}
}
if((lv->exptype==VALUE)&&(lv->cval==1))
{ expr->rval=NULL;
freetree(expr);
return simplify(rv);
}
if((lv->exptype==VALUE)&&(lv->cval==-1))
{ expr->lval=NULL;
freetree(lv);
expr->expval.op=UMINUS;
return simplify(expr);
}
if((rv->exptype==VALUE)&&(rv->cval==1))
{ expr->lval=NULL;
freetree(expr);
return simplify(lv);
}
if((lv->exptype==VALUE)&&(lv->cval==0))
{ expr->lval=NULL;
freetree(expr);
return lv;
}
if((rv->exptype==VALUE)&&(rv->cval==0))
{ expr->rval=NULL;
freetree(expr);
return rv;
}
if((lv->exptype==VALUE)&&(rv->exptype==VALUE))
{ lv->cval*=rv->cval;
expr->lval=NULL;
freetree(expr);
return simplify(lv);
}
if((lv->exptype==VALUE)&&(rv->exptype==OPERATOR))
{ if((rv->expval.op==TIMES)&&(rv->lval->exptype==VALUE))
{ rv->lval->cval*=lv->cval;
expr->rval=NULL;
freetree(expr);
return simplify(rv);
}
}
if(equaltrees(lv,rv))
{ expr->lval=NULL;
freetree(expr);
expr=newtree();
rv=newtree();
expr->exptype=OPERATOR;
expr->expval.op=POWER;
expr->lval=lv;
expr->rval=rv;
rv->exptype=VALUE;
rv->cval=2;
return simplify(expr);
}
if((lv->exptype==OPERATOR)&&(rv->exptype==OPERATOR))
{ if((lv->expval.op==DIVIDE)&&(rv->expval.op==POWER))
if(equaltrees(lv->rval,rv->lval))
{ lv=lv->lval;
expr->lval->lval=NULL;
freetree(expr->lval);
expr->lval=lv;
rv=newtree();
rv->exptype=OPERATOR;
rv->expval.op=MINUS;
rv->lval=expr->rval->rval;
expr->rval->rval=rv;
rv=newtree();
rv->exptype=VALUE;
rv->cval=1;
expr->rval->rval->rval=rv;
return simplify(expr);
}
else
if((lv->expval.op==TIMES)&&(rv->expval.op==POWER))
if(equaltrees(lv->rval,rv->lval))
{ lv=lv->lval;
expr->lval->lval=NULL;
freetree(expr->lval);
expr->lval=lv;
rv=newtree();
rv->exptype=OPERATOR;
rv->expval.op=PLUS;
rv->lval=expr->rval->rval;
expr->rval->rval=rv;
rv=newtree();
rv->exptype=VALUE;
rv->cval=1;
expr->rval->rval->rval=rv;
return simplify(expr);
}
}
if(rv->exptype==OPERATOR)
{ if(rv->expval.op==POWER)
{ if(equaltrees(lv,rv->lval))
{ expr->rval=NULL;
freetree(expr);
expr=rv;
rv=newtree();
rv->exptype=OPERATOR;
rv->expval.op=PLUS;
rv->lval=expr->rval;
expr->rval=rv;
rv=newtree();
rv->exptype=VALUE;
rv->cval=1;
expr->rval->rval=rv;
return simplify(expr);
}
else
if((rv->rval->exptype==VALUE)&&(rv->rval->cval<0))
{ expr->expval.op=DIVIDE;
rv->rval->cval=-rv->rval->cval;
return simplify(expr);
}
else
if((rv->rval->exptype==OPERATOR)&&(rv->rval->expval.op==UMINUS))
{ expr->expval.op=DIVIDE;
rv=rv->rval->rval;
expr->rval->rval->rval=NULL;
freetree(expr->rval->rval);
expr->rval->rval=rv;
return simplify(expr);
}
}
else
if(rv->expval.op==UMINUS)
{ expr->rval=expr->rval->rval;
rv->rval=expr;
return simplify(rv);
}
else
if((rv->expval.op==TIMES)||(rv->expval.op==DIVIDE))
{ if(equaltrees(lv,rv->lval))
{ expr->rval=NULL;
freetree(expr);
expr=rv;
lv=newtree();
lv->exptype=OPERATOR;
lv->expval.op=POWER;
lv->lval=expr->lval;
expr->lval=lv;
lv=newtree();
lv->exptype=VALUE;
lv->cval=2;
expr->lval->rval=lv;
return simplify(expr);
}
}
}
if(lv->exptype==OPERATOR)
{ if(lv->expval.op==POWER)
{ if(equaltrees(lv->lval,rv))
{ expr->lval=NULL;
freetree(expr);
expr=lv;
lv=newtree();
lv->exptype=OPERATOR;
lv->expval.op=PLUS;
lv->lval=expr->rval;
expr->rval=lv;
rv=newtree();
rv->exptype=VALUE;
rv->cval=1;
expr->rval->rval=rv;
return simplify(expr);
}
}
else
if(lv->expval.op==UMINUS)
{ expr->lval=expr->lval->rval;
lv->rval=expr;
return simplify(lv);
}
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==POWER)&&
(rv->exptype==OPERATOR)&&(rv->expval.op==POWER))
if(equaltrees(lv->lval,rv->lval))
{ lv=newtree();
lv->exptype=OPERATOR;
lv->expval.op=PLUS;
lv->rval=rv->rval;
lv->lval=expr->lval->rval;
rv->rval=lv;
expr->lval->rval=NULL;
expr->rval=NULL;
freetree(expr);
return simplify(rv);
}
break;
case PLUS: if((lv->exptype==OPERATOR)&&(lv->expval.op==PLUS))
{ expr->lval=lv->rval;
lv->rval=expr;
return simplify(lv);
}
if((rv->exptype==OPERATOR)&&(rv->expval.op==PLUS))
{ if((lv->exptype)<(rv->lval->exptype))
{ expr->lval=rv->lval;
rv->lval=lv;
lv=expr->lval;
return simplify(expr);
}
}
if((lv->exptype==VALUE)&&(lv->cval==0))
{ expr->rval=NULL;
freetree(expr);
return rv;
}
if((rv->exptype==VALUE)&&(rv->cval==0))
{ expr->lval=NULL;
freetree(expr);
return lv;
}
if((lv->exptype==VALUE)&&(rv->exptype==VALUE))
{ lv->cval+=rv->cval;
expr->lval=NULL;
freetree(expr);
return lv;
}
if((rv->exptype==VALUE)&&(rv->cval<0))
{ expr->exptype=MINUS;
rv->cval=-rv->cval;
return expr;
}
if((rv->exptype==OPERATOR)&&(rv->expval.op==UMINUS))
{ expr->expval.op=MINUS;
expr->rval=expr->rval->rval;
rv->rval=NULL;
freetree(rv);
return simplify(expr);
}
break;
case MINUS: if((lv->exptype==VALUE)&&(rv->exptype==VALUE))
{ lv->cval-=rv->cval;
expr->lval=NULL;
freetree(expr);
return simplify(lv);
}
if((lv->exptype==VALUE)&&(lv->cval==0))
{ expr->lval=NULL;
expr->expval.op=UMINUS;
freetree(lv);
return simplify(expr);
}
if((rv->exptype==VALUE)&&(rv->cval==0))
{ expr->lval=NULL;
freetree(expr);
return lv;
}
if((rv->exptype==VALUE)&&(rv->cval<0))
{ expr->exptype=PLUS;
rv->cval=-rv->cval;
return expr;
}
if((rv->exptype==OPERATOR)&&(rv->expval.op==UMINUS))
{ expr->expval.op=PLUS;
expr->rval=expr->rval->rval;
rv->rval=NULL;
freetree(rv);
return simplify(expr);
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==UMINUS))
{ expr->expval.op=PLUS;
expr->lval=lv->rval;
lv->rval=expr;
return simplify(lv);
}
if((rv->exptype==OPERATOR)&&(rv->expval.op==MINUS))
{ expr->expval.op=PLUS;
expr->lval=expr->rval->rval;
expr->rval->rval=expr->rval->lval;
expr->rval->lval=lv;
return simplify(expr);
}
break;
case UMINUS: if((rv->exptype==VALUE)&&(rv->cval<=0))
{ rv->cval=-rv->cval;
expr->rval=NULL;
freetree(expr);
return rv;
}
if((rv->exptype==OPERATOR)&&(rv->expval.op==UMINUS))
{ rv=rv->rval;
expr->rval->rval=NULL;
freetree(expr);
return rv;
}
break;
case DIVIDE: if((rv->exptype==OPERATOR)&&(rv->expval.op==TIMES))
{ while((rv->exptype==OPERATOR)&&(rv->expval.op==TIMES))
{ if(equaltrees(rv->lval,lv))
{ freetree(lv);
lv=newtree();
lv->exptype=VALUE;
lv->cval=1;
expr->lval=lv;
freetree(rv->lval);
lv=newtree();
lv->exptype=VALUE;
lv->cval=1;
rv->lval=lv;
return simplify(expr);
}
if(equaltrees(rv->rval,lv))
{ freetree(lv);
lv=newtree();
lv->exptype=VALUE;
lv->cval=1;
expr->lval=lv;
freetree(rv->rval);
lv=newtree();
lv->exptype=VALUE;
lv->cval=1;
rv->rval=lv;
return simplify(expr);
}
rv=rv->rval;
}
rv=expr->rval;
}
if((lv->exptype==VALUE)&&(rv->exptype==VALUE))
{ lv->cval/=rv->cval;
expr->lval=NULL;
freetree(expr);
return lv;
}
if(rv->exptype==VALUE)
{ expr->expval.op=TIMES;
rv->cval=1/rv->cval;
return simplify(expr);
}
if(equaltrees(lv,rv))
{ freetree(expr);
expr=newtree();
expr->exptype=VALUE;
expr->cval=1;
return expr;
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==TIMES))
{ expr->expval.op=TIMES;
expr->rval=lv;
expr->rval->expval.op=DIVIDE;
expr->lval=expr->rval->lval;
expr->rval->lval=expr->rval->rval;
expr->rval->rval=rv;
return simplify(expr);
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==DIVIDE))
{ lv->expval.op=TIMES;
expr->rval=lv;
expr->lval=expr->rval->lval;
expr->rval->lval=expr->rval->rval;
expr->rval->rval=rv;
return simplify(expr);
}
if((rv->exptype==OPERATOR)&&(rv->expval.op==DIVIDE))
{ expr->expval.op=TIMES;
rv=rv->rval;
expr->rval->rval=expr->rval->lval;
expr->rval->lval=rv;
return simplify(expr);
}
if((rv->exptype==OPERATOR)&&(rv->expval.op==POWER))
if(!((rv->rval->exptype==VALUE)&&(rv->rval->cval>=0)))
{ expr->expval.op=TIMES;
rv=newtree();
rv->exptype=OPERATOR;
rv->expval.op=UMINUS;
rv->rval=expr->rval->rval;
expr->rval->rval=rv;
return simplify(expr);
}
else
if(equaltrees(lv,rv->lval))
{ expr->rval=NULL;
freetree(expr);
lv=newtree();
lv->exptype=OPERATOR;
lv->expval.op=MINUS;
lv->rval=rv->rval;
rv->rval=lv;
lv=newtree();
lv->exptype=VALUE;
lv->cval=1;
rv->rval->lval=lv;
return simplify(rv);
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==POWER))
if(equaltrees(lv->lval,rv))
{ expr->lval=NULL;
freetree(expr);
rv=newtree();
rv->exptype=OPERATOR;
rv->expval.op=MINUS;
rv->lval=lv->rval;
lv->rval=rv;
rv=newtree();
rv->exptype=VALUE;
rv->cval=1;
lv->rval->rval=rv;
return simplify(lv);
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==UMINUS))
{ expr->lval=lv->rval;
lv->rval=expr;
return simplify(lv);
}
if((rv->exptype==OPERATOR)&&(rv->expval.op==UMINUS))
{ expr->rval=rv->rval;
rv->rval=expr;
return simplify(rv);
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==POWER)&&
(rv->exptype==OPERATOR)&&(rv->expval.op==POWER))
if(equaltrees(lv->lval,rv->lval))
{ lv=newtree();
lv->exptype=OPERATOR;
lv->expval.op=MINUS;
lv->rval=rv->rval;
lv->lval=expr->lval->rval;
rv->rval=lv;
expr->lval->rval=NULL;
expr->rval=NULL;
freetree(expr);
return simplify(rv);
}
break;
case POWER: if((rv->exptype==VALUE)&&(rv->cval==1))
{ expr->lval=NULL;
freetree(expr);
return lv;
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==POWER))
if((lv->rval->exptype==VALUE)&&(rv->exptype==VALUE))
{ lv->rval->cval*=rv->cval;
expr->lval=NULL;
freetree(expr);
return lv;
}
if((lv->exptype==OPERATOR)&&(lv->expval.op==UMINUS))
if((rv->exptype==VALUE))
{ if((float)((int)(rv->cval/2))==(rv->cval/2))
{ expr->lval=expr->lval->rval;
lv->rval=NULL;
freetree(lv);
return simplify(expr);
}
else
if((float)((int)((rv->cval-1)/2))==((rv->cval-1)/2))
{ expr->lval=expr->lval->rval;
lv->rval=expr;
return simplify(lv);
}
}
break;
case UNDEF_OP:
default: break;
}
}
return expr;
}